package com.good.shopping.product.redis;

import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 3 .分布式锁
 *      可重入锁
 *      读写锁
 *      信号量
 *      闭锁
 * @author shengren.yan
 * @create 2022-02-24
 */
public class redis3 {

    @Autowired
    RedissonClient redisson;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    // 1.分布式锁 - 可重入锁
    public String test1() {

        RLock lock = redisson.getLock("my-lock");
        try {
            // 1 阻塞式等待，默认加的锁都是30s 锁的自动续期，
            //   如果业务超长，运行期间自动给锁续上新的30s。不用担心业务时间长，锁自动过期被删除
            lock.lock();
            // 2 加锁 20s自动解锁
            // lock.lock(20, TimeUnit.SECONDS);
            // 3 尝试加锁 最多等待100秒，超时就不等了
            boolean b = lock.tryLock(100, 10, TimeUnit.SECONDS);
            System.out.println("查看有没有获取到锁" + b);

            System.out.println("加锁成功，执行业务代码，，，");
            Thread.sleep(30000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "ok";
    }

    // 公平锁   RLock fairLock = redisson.getFairLock("my-lock");

    // 2.分布式 读写锁
    // 写 + 读 等待写完，再读
    // 写 + 写 阻塞等待
    // 读 + 写 有读锁，写也等待
    // 读 + 读 共享锁
    public String test2Read() {

        RReadWriteLock readWriteLock = redisson.getReadWriteLock("rw-lock");
        RLock lock = readWriteLock.readLock();
        try {
            lock.lock();
            System.out.println("读锁。。。");
            String wr = stringRedisTemplate.opsForValue().get("wr");
            System.out.println(wr);
//            Thread.sleep(30000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

        // JUC 包下的本地
//        ReentrantReadWriteLock readWriteLock1 = new ReentrantReadWriteLock();
//        Lock lock1 = readWriteLock1.readLock();
//        Lock lock2 = readWriteLock1.writeLock();

        return "ok";
    }

    // 2.分布式 读写锁
    public String test2Write() {
        String s = UUID.randomUUID().toString();
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("rw-lock");
        RLock lock = readWriteLock.writeLock();
        try {
            lock.lock(10,TimeUnit.SECONDS);
            System.out.println("写锁。。。");
            Thread.sleep(30000);
            stringRedisTemplate.opsForValue().set("wr",s);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "ok";
    }


    // 信号量
    // 停车位
    // 信号量 - 停车位 - 需要在redis设置一个值
    public String park() {
        RSemaphore semaphore = redisson.getSemaphore("seme-lock");
        try {
            // semaphore.acquire(); // 获取一个信号
            System.out.println("获取一个信号");
            // 尝试获取信号
            boolean b = semaphore.tryAcquire();
            if(b){
                System.out.println("获取到了");
            }else {
                System.out.println("没有获取到，用于限流，做一些提示");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        // JUC 包下的本地
//        Semaphore semaphore1 = new Semaphore(5);
//        semaphore1.release();
//        semaphore1.acquire();

        return "ok";
    }

    // 信号量 - 停车位
    public String go() {
        RSemaphore semaphore = redisson.getSemaphore("seme-lock");
        try {
            semaphore.release(); // 释放一个信号
            System.out.println("释放");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "释放";
    }

    // 闭锁 - 3人全揍-锁门 ，全部执行完才能执行锁门操作
    public String lockDoor() {
        RCountDownLatch door = redisson.getCountDownLatch("door");
        try {
            door.trySetCount(3); // 设置满3个 就锁门
            door.await(); // 等待都完成
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
        }

        // JUC 包下的本地
//        CountDownLatch countDownLatch = new CountDownLatch(3);
//        countDownLatch.await();
//        countDownLatch.countDown();


        return "锁门";
    }

    // 信号量 - 停车位
    public String goTe() {
        Long id = 1L; // 计数
        RCountDownLatch door = redisson.getCountDownLatch("door");
        try {
            door.countDown(); // 计数 -1
            System.out.println("释放");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
        }
        return id +" ：释放";
    }

}
